/**
 * @Author Yunfeng Bai
 *
 * 2010-10-30
 */
package collision;

import geometry.Box;
import geometry.Drawable;
import geometry.Triangle;
import geometry.TriangleMesh;
import geometry.TriangleMesh.TriangleIndex;

import java.util.List;

import javax.media.opengl.GL2;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

public class BoundingBox extends BoundingVolume
{
    public Drawable _object;
    public Point3d _minPt = new Point3d();
    public Point3d _maxPt = new Point3d();
    private TriangleMesh mesh;

    public BoundingBox()
    {
    }

    public BoundingBox(Drawable object_, Point3d minPt_, Point3d maxPt_)
    {
        _object = object_;
        _minPt.set(minPt_);
        _maxPt.set(maxPt_);
    }

    public BoundingBox clone()
    {
        return new BoundingBox(_object, _minPt, _maxPt);
    }

    /**
     * Extends this bounding box by another one.
     */
    public void extend(BoundingBox box_)
    {
        if (box_._minPt.x < _minPt.x)
            _minPt.x = box_._minPt.x;
        if (box_._maxPt.x > _maxPt.x)
            _maxPt.x = box_._maxPt.x;
        if (box_._minPt.y < _minPt.y)
            _minPt.y = box_._minPt.y;
        if (box_._maxPt.y > _maxPt.y)
            _maxPt.y = box_._maxPt.y;
        if (box_._minPt.z < _minPt.z)
            _minPt.z = box_._minPt.z;
        if (box_._maxPt.z > _maxPt.z)
            _maxPt.z = box_._maxPt.z;
    }

    @Override
	public void build(GL2 gl)
	{
		double length = _maxPt.x - _minPt.x;
		double width = _maxPt.y - _minPt.y;
		double height = _maxPt.z - _minPt.z;
		
		Box box = new Box(length, width, height);
		mesh = box.getTriangleMesh();
		
		_listNum = gl.glGenLists(1);
		gl.glNewList(_listNum, GL2.GL_COMPILE);
		
		gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
		
		for(Triangle t : mesh._triangles)
			t.draw(gl);
		
		gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
		
		gl.glEndList();
	}

	@Override
	public TriangleMesh getTriangleMesh()
	{
		return mesh;
	}

	@Override
	public BoundingBox getBoundingBox()
	{
		// No need to get the bounding box of a BoundingBox.
		return null;
	}

	@Override
	public boolean isColliding(BoundingVolume obj_)
	{
		if ((obj_ instanceof BoundingSphere) == false)
            throw new IllegalArgumentException(
                    "BoundingSphere can only collide with BoundingSphere");
        BoundingBox box = (BoundingBox) obj_;

        return ((_minPt.x < box._maxPt.x) && (_maxPt.x > box._minPt.x)
                && (_minPt.y < box._maxPt.y) && (_maxPt.y > box._minPt.y)
                && (_minPt.z < box._maxPt.z) && (_maxPt.z > box._minPt.z));
	}
}
